Aller au contenu principal

Kubernetes - Déploiement


Les machines

1 master et autant de worker que voulus seront utilisé.

Le tutoriel à été fait sur Ubuntu 20.04, avec la box vagrant bento/ubuntu20.04, version de box « 202112.19.0 » sur le provider Vmware Workstation.

2GB de Ram par machine suffisent..

Version de Vagrant (Windows) utilisée : Pasted image 20230217130911.png N :B : ovftools doit être installé sur votre machine pour le déploiement sur Workstation !

Le Vagrant file

IMAGE_NAME = "bento/ubuntu-20.04"   # Image to use
MEM = 2048                          # Amount of RAM
CPU = 2                             # Number of processors (Minimum value of 2 otherwise it will not work)
MASTER_NAME="master"                # Master node name
NODE_NETWORK_BASE = "192.168.45"    # First three octets of the IP address that will be assign to all type of nodes
nodes = [

  { hostname: MASTER_NAME, box: IMAGE_NAME, mac:'00:50:56:25:03:95', numvcpus:'2', ip:"#{NODE_NETWORK_BASE}.30" },

  { hostname: 'worker-1', box:'bento/ubuntu-20.04', mac:'00:50:56:26:11:98', numvcpus:'2', ip:"#{NODE_NETWORK_BASE}.27"  },

  { hostname: 'worker-2', box:'bento/ubuntu-20.04', mac:'00:50:56:27:11:98', numvcpus:'2', ip:"#{NODE_NETWORK_BASE}.28"  }

]

Vagrant.configure("2") do |config|
  nodes.each do |node|
  config.vm.define node[:hostname] do |config|

    config.vm.synced_folder('.', '/Vagrantfiles', type: 'rsync')
    config.vm.box = node[:box]
    config.vm.box_version = "202112.19.0"
    config.vm.hostname= node[:hostname]
    config.vm.disk :disk, size: "20GB", primary: true
    config.vm.boot_timeout = 100
    config.vm.graceful_halt_timeout = 100
config.ssh.insert_key = false


config.vm.provision "shell", path: "install.sh"

    config.vm.provider "vmware_desktop" do |v|
      v.gui = true
      nat_device = "vmnet8"
      v.linked_clone = false
      v.vmx["ethernet0.connectionType"]  = "nat"
      v.vmx["memsize"] = "2048"
      v.vmx["numvcpus"] = "2"
      v.vmx["virtualHW.version"] = "11" #compatible Esxi 6.5
      v.vmx["ethernet0.present"] = "true"
      v.vmx["scsi0:0.size"] = "40000"
    end  
  end
end
end

install.sh

#!/bin/bash

# Update the system
apt-get update -y
# Install the required packages
apt-get install -y vim net-tools sudo ssh curl htop open-vm-tools dnsutils gpg
# Usefull libs
sudo snap install yq
# Couples of prerequisites
sudo apt-get update
echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
sudo modprobe overlay
sudo modprobe br_netfilter

# NFS client
sudo apt-get install -y nfs-common

Puis rendez-vous dans le dossier en ligne de commande (ici Powershell en mode administrateur) ou se trouve votre Vagrantfile puis lancer la commande :

vagrant up

Pasted image 20230217131211.png

Installation de docker, kubeadm, kubelet et kubectl

Pré-requis

Sur la machine qui sera le master et sur toutes les autres machines, assurez-vous d'avoir installé les outils de base pour Kubernetes tels que Docker et kubeadm en suivant les instructions d'installation pour Ubuntu

sudo apt-get update

sudo apt-get install -y apt-transport-https ca-certificates curl gnupg-agent software-properties-common gpg bash-completion

sudo mkdir -p /etc/apt/keyrings

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

sudo apt-get update

sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin -y

curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -

echo "deb https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee -a /etc/apt/sources.list.d/kubernetes.list

sudo apt-get update

sudo apt-get install -y kubeadm kubelet kubectl

sudo usermod -aG docker $USER && newgrp docker #Uniquement si vous utilisez docker avec un utilisateur non root (ce sera normalement le cas)
Important

Une fois ces prérequis installés, vous pouvez soit installer minikube, kind, ou un cluster k8s.

Minikube

Installer minikube.

curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64

chmod +x minikube

sudo mv minikube /usr/local/bin/

curl -sSL https://get.docker.com | sh

minikube start [options]

kubectl get node
NAME       STATUS   ROLES                            AGE   VERSION
minikube   Ready    control-plane,master   40m   v1.20.0

Créer un cluster avec minikube :

$ minikube start --driver docker --nodes 3
😄  minikube v1.28.0 on Debian 11.5
✨  Using the docker driver based on user configuration
📌  Using Docker driver with root privileges
👍  Starting control plane node minikube in cluster minikube
🚜  Pulling base image ...
🔥  Creating docker container (CPUs=2, Memory=2200MB) ...
🐳  Preparing Kubernetes v1.25.3 on Docker 20.10.20 ...
[]
🔗  Configuring CNI (Container Networking Interface) ...
[]
👍  Starting worker node minikube-m02 in cluster minikube
[]
🔎  Verifying Kubernetes components...
👍  Starting worker node minikube-m03 in cluster minikube
🚜  Pulling base image ...
🔥  Creating docker container (CPUs=2, Memory=2200MB) ...
[]
🔎  Verifying Kubernetes components...
🏄  Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default

Puis essayer: Pasted image 20230217131542.png

Cluster Kind

Kind (Kubernetes in Docker) permet de déployer un cluster Kubernetes de façon à ce que chacun des nodes du cluster tourne dans un container Docker.

Pour l'utiliser il suffit simplement d'installer Docker ainsi que la dernière release de Kind (https://github.com/kubernetes-sigs/kind/releases).

curl -Lo ./kind "https://kind.sigs.k8s.io/dl/v0.17.0/kind-$(uname)-amd64"
chmod +x ./kind
sudo mv ./kind /usr/local/bin/kind
vagrant@worker-1:~$ kind
kind creates and manages local Kubernetes clusters using Docker container 'nodes'
Usage:
  kind [command]
Available Commands:
  build       Build one of [node-image]
  completion  Output shell completion code for the specified shell (bash, zsh or fish)
  create      Creates one of [cluster]
  delete      Deletes one of [cluster]
  export      Exports one of [kubeconfig, logs]
  get         Gets one of [clusters, nodes, kubeconfig]
  help        Help about any command
  load        Loads images into nodes
  version     Prints the kind CLI version

Flags:

  -h, --help              help for kind
      --loglevel string   DEPRECATED: see -v instead
  -q, --quiet             silence all stderr output
  -v, --verbosity int32   info log verbosity, higher value produces more output
      --version           version for kind
Use "kind [command] --help" for more information about a command.

Créer le cluster k8S.

kind create cluster --name k8s

HA Clusters

Kind permet également de mettre en place un cluster comportant plusieurs nodes, pour cela il faut utiliser un fichier de configuration. Par exemple, le fichier suivant (config.yaml) définit un cluster de 3 nodes: 1 master et 2 workers.

# config.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: worker
- role: worker
kind create cluster --name k8s-2 --config config.yaml
kind get clusters

Cluster K8S

Ne pas oublier d’installer DOCKER, KUBEADM, KUBELET ET KUBECTL, vu précédemment, sur chaque machine, master comme worker.

Pré-requis

Commun aux masters et workers

Installer d’abord les dépendances nécessaires (container runtime et quelques packages).

#curl -sSL https://luc.run/kubeadm/master.sh | bash 
$ sudo swapoff -a #Désactiver le swap
attention

L'installation avec le curl n'est pas forcément nécessaire, c'est un script préconçu de configuration initiale, qui peut différer suivant comment on décicde d'installer notre cluster. Si vous avez respectez les prérequis précédent, il ne sera normalement pas obligatoire.

Voici le contenu initial du script, cela peut aider :

# Set current version
VERSION=${VERSION:-"1.25.2"}

# Useful alias
echo 'alias k="kubectl"' >> $HOME/.bashrc

# Usefull libs
sudo snap install yq

# Cleanup first
rm -rf $HOME/.kube
sudo kubeadm reset -f || true
sudo apt-mark unhold kubelet kubeadm kubectl || true
sudo apt-get remove -y containerd kubelet kubeadm kubectl kubernetes-cni || true
sudo apt-get autoremove -y
sudo systemctl daemon-reload

# Couples of prerequisites
sudo apt-get update
echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
sudo modprobe overlay
sudo modprobe br_netfilter

# NFS client
sudo apt-get install -y nfs-common

# Installing packages
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
sudo apt-add-repository "deb http://apt.kubernetes.io/ kubernetes-xenial main"
sudo apt-get update
sudo apt-get install -y kubelet=${VERSION}-00 kubeadm=${VERSION}-00 kubectl=${VERSION}-00 kubernetes-cni

# Installing Containerd
sudo apt-get install containerd -y
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/g' /etc/containerd/config.toml  

sudo service containerd restart
sudo service kubelet restart  

# Installing Helm client
sudo snap install helm --classic

# Configure crictl to use Containerd (it uses Docker by default)
cat <<EOF | sudo tee /etc/crictl.yaml
runtime-endpoint: unix:///run/containerd/containerd.sock
EOF

# Install etcdctl (linux amd64 or arm64)
ARCH=$(dpkg --print-architecture)
ETCDCTL_VERSION=v3.5.2
ETCDCTL_VERSION_FULL=etcd-${ETCDCTL_VERSION}-linux-$ARCH
wget https://github.com/etcd-io/etcd/releases/download/${ETCDCTL_VERSION}/${ETCDCTL_VERSION_FULL}.tar.gz
tar xzf ${ETCDCTL_VERSION_FULL}.tar.gz
sudo mv ${ETCDCTL_VERSION_FULL}/etcdctl /usr/bin/
rm -rf ${ETCDCTL_VERSION_FULL} ${ETCDCTL_VERSION_FULL}.tar.gz

# Install nerdctl
NERDCTL_VERSION=0.17.0
wget https://github.com/containerd/nerdctl/releases/download/v${NERDCTL_VERSION}/nerdctl-${NERDCTL_VERSION}-linux-${ARCH}.tar.gz
sudo tar Cxzvvf /usr/local/bin nerdctl-${NERDCTL_VERSION}-linux-${ARCH}.tar.gz
rm nerdctl-${NERDCTL_VERSION}-linux-${ARCH}.tar.gz

# Install useful kubectl aliases
curl -sSLO https://raw.githubusercontent.com/ahmetb/kubectl-aliases/master/.kubectl_aliases
echo '[ -f ~/.kubectl_aliases ] && source ~/.kubectl_aliases' >> .bashrc

Commenter la ligne dans /etc/fstab comme sur l’exemple pour définitivement désactiver le swap. Pasted image 20230217132030.png Setup proprement votre hostname : hostnamectl set-hostname master

Puis ajouter votre IP et nom d’hôte dans le /etc/hosts Pasted image 20230217132036.png

Assurez-vous que containerd.io ne fasse pas conflit :

sudo rm /etc/containerd/config.toml
sudo systemctl restart containerd

Ajouter au fichier /etc/docker/daemon.json

{ "exec-opts": ["native.cgroupdriver=systemd"],
            "log-driver": "json-file",
            "log-opts":
            { "max-size": "100m" },
            "storage-driver": "overlay2"
}

Puis activer au démarrage :

sudo systemctl enable docker
sudo systemctl daemon-reload
sudo systemctl restart docker

Redémarrer les machines.


Dans chacune des machines, chercher la ligne suivant au fichier /etc/systemd/system/kubelet.service.d/10-kubeadm.conf

Environment="KUBELET_EXTRA_ARGS=--node-ip=192.168.45.170"

Pasted image 20230217132207.png

Vous devez changer l’ip pour mettre l’ip de la machine, ici c’est le master, et pour nos worker ce sera 192.168.45.171 et 192.168.45.172 par exemple.

Redémarrer kubelet pour valider.

sudo systemctl daemon-reload
sudo systemctl restart kubelet

Modifier /etc/containerd/config.toml pour y avoir le contenu suivant :

#   Copyright 2018-2022 Docker Inc.
#
#   Licensed under the Apache License, Version 2.0 (the "License");
#   you may not use this file except in compliance with the License.
#   You may obtain a copy of the License at
#       http://www.apache.org/licenses/LICENSE-2.0
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.
disabled_plugins = []

[plugins."io.containerd.grpc.v1.cri"]

    systemd_cgroup = true

#root = "/var/lib/containerd"
#state = "/run/containerd"
#subreaper = true
#oom_score = 0
#[grpc]
#  address = "/run/containerd/containerd.sock"
#  uid = 0
#  gid = 0
#[debug]
#  address = "/run/containerd/debug.sock"
#  uid = 0
#  gid = 0
#  level = "info"

Puis redémarrer : sudo systemctl restart containerd Puis reboot

Prérequis pour le master

1)    Editer le fichier /etc/docker/daemon.json et y ajouter :

{
"exec-opts": ["native.cgroupdriver=systemd"]
}
sudo systemctl enable docker
sudo systemctl daemon-reload
sudo systemctl restart docker

Master

1)    Initialisez le contrôleur de cluster sur le master en utilisant la commande

sudo kubeadm init --apiserver-advertise-address=192.168.45.170 --apiserver-cert-extra-sans=192.168.45.170 --node-name=master --pod-network-cidr=10.244.0.0/16 --ignore-preflight-errors=NumCPU,Mem
remarque

le flag --ignore-preflight-errors permet de forcer l'installation même si les requirements en terme de CPU et Mémoire ne sont pas respectés (cette option ne sera évidemment pas utilisée pour la mise en place d'un cluster de production)

2)    Configurez kubectl pour utiliser le nouveau cluster en utilisant les commandes générées par la commande kubeadm init

rm -rf /home/$USER/.kube
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
export KUBECONFIG=$HOME/.kube/config

3)    Mettez en place le réseau, ici avec flannel :

kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

mkdir -p /run/flannel/
touch /run/flannel/subnet.env

Ajouter dans le fichier /run/flannel/subnet.env

FLANNEL_NETWORK=10.244.0.0/16
FLANNEL_SUBNET=10.244.0.1/24
FLANNEL_MTU=1450
FLANNEL_IPMASQ=true

Vous récupérerez une commande kubeadm join – Gardez la de côté ou vous pouvez la retrouver avec

sudo kubeadm token create --print-join-command

Exemple :

sudo kubeadm join 192.168.45.163:6443 --token tv6ynl.getnsnh1sa4u8j87         --discovery-token-ca-cert-hash sha256:9c6531aaa77ca6b3f145dc0b6ee7421ac1fefcb3421b22b5fd5474341451ba08

-----> [preflight] Running pre-flight checks
[...]

Worker

Ajoutez les 2 nœuds au cluster en utilisant la commande kubeadm join sur chacune des machines en utilisant les informations générées par la commande kubeadm init sur le master.

Créez un fichier de configuration pour chaque nœud avec la commande :

sudo kubeadm alpha node config --node-name=NODE_NAME > NODE_NAME-config.yaml

Appliquez la configuration pour chaque nœud en utilisant la commande :

sudo kubeadm join --config NODE_NAME-config.yaml

Ou copier simplement la commande précédemment générée de type :

kubeadm join 192.168.45.163:6443 --token tv6ynl.getnsnh1sa4u8j87         --discovery-token-ca-cert-hash sha256:9c6531aaa77ca6b3f145dc0b6ee7421ac1fefcb3421b22b5fd5474341451ba08

Configurez kubectl pour utiliser le nouveau cluster en utilisant les commandes générées par la commande kubeadm init

Exemple :

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

Vérifiez que le cluster est opérationnel en exécutant la commande :

kubectl get nodes

Vérifiez que tous les nœuds sont en état "Ready"

Utilisez les commandes de base de kubectl pour gérer le cluster.

Troubleshooting

Reset le cluster en cas de problème pour refaire un kubeadm init ou kubeadm join ensuite.

sudo kubeadm reset -f
rm -rf $HOME/.kube/config

Puis refaire à partir l’étape 1 du master.

Redémarrer proprement

sudo systemctl daemon-reload
sudo systemctl stop kubelet
sudo systemctl start kubelet
sudo systemctl stop docker
sudo systemctl start docker
kubectl get pods -A -o wide
kubectl get pods -n kube-system

Supprimer flannel pour qu’il se reconstruise :

kubectl delete pods kube-flannel-ds-mjzjn -n kube-flannel
kubectl delete pods kube-flannel-ds-2ksgt -n kube-flannel

Liens utiles

Screenshots de fonctionnement

Pasted image 20230217133015.png

Pasted image 20230217133044.png

Pasted image 20230217133051.png

Pasted image 20230217133057.png